#include "../StdAfx.h"
#include "NetServer.h"

NetServer* NetServer::mInstance = new NetServer();

NetServer* NetServer::getInstance()
{
	assert( mInstance );
	return mInstance;
}

NetServer::NetServer()
			: mAcceptor(mIoService)
{

}

void NetServer::init(std::string port)
{
	
	init(port,40);

}

void NetServer::init(std::string port,size_t tpSize)
{

	mThreadPoolSize = tpSize;
	boost::asio::ip::tcp::resolver _resolver(mIoService);
	boost::asio::ip::tcp::resolver::query _query(boost::asio::ip::tcp::v4(), port);
	boost::asio::ip::tcp::endpoint _endpoint = *_resolver.resolve(_query);

	mAcceptor.open(_endpoint.protocol());
	mAcceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
	mAcceptor.bind(_endpoint);
	mAcceptor.listen();

	mConn.reset(new Connection(mIoService));

	mAcceptor.async_accept(mConn->getSocket(), boost::bind(
			&NetServer::handleAccept, this, boost::asio::placeholders::error));

}

NetServer::~NetServer()
{
	Log->success("~NetServer");
}

void NetServer::handleAccept(const boost::system::error_code& e)
{

	if ( !e )
	{

		mConn->start();

		mMuxMap.lock();
		mClientsVector.insert(mConn);
		mMuxMap.unlock();

		Log->info("Conexion aceptada [%d conexiones]", mClientsVector.size());

		mConn.reset(new Connection(mIoService));

		mAcceptor.async_accept(mConn->getSocket(), boost::bind(
					&NetServer::handleAccept, this, boost::asio::placeholders::error));

	}

}

void NetServer::run()
{

	std::size_t _i;

	for ( _i = 0; _i < mThreadPoolSize; _i++ )
	{

		boost::shared_ptr<boost::thread> thread(new boost::thread(boost::bind(&boost::asio::io_service::run, &mIoService)));
		mThreads.push_back(thread);

	}

	Log->success("NetServer started.");

}

void NetServer::stop()
{

	std::size_t _i;

	mIoService.post(boost::bind(&NetServer::stopAllConnections,this));

	for ( _i = 0; _i < mThreads.size(); ++_i )
	{

		boost::thread::id thId = mThreads[_i]->get_id();
		mThreads[_i]->join();
		//Log->info("ThreadId[%d] exit success",_i);

	}

	Log->success("NetServer stopped");
	delete Net;

}

void NetServer::removeConnection(connection_ptr con)
{

	mMuxMap.lock();
	mClientsVector.erase(con);
	Log->info("Cerrando conexion [%d conexiones]", mClientsVector.size());
	mMuxMap.unlock();

}

void NetServer::stopAllConnections()
{
	mAcceptor.close();
	std::for_each(mClientsVector.begin(), mClientsVector.end(),
      boost::bind(&Connection::close, _1));
	mClientsVector.clear();
}
